package com.five.admin.server.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.five.admin.dto.ProductEditDto;
import com.five.admin.dto.ProductQueryDto;
import com.five.admin.mapper.ProductMapper;
import com.five.admin.server.BrandService;
import com.five.admin.server.ImageService;
import com.five.admin.server.ProductImageService;
import com.five.admin.server.ProductService;
import com.five.admin.vo.ProductAdminVo;
import com.five.admin.vo.ProductDetailsVo;
import com.five.pojo.dto.ProductAddDto;
import com.five.pojo.entity.Image;
import com.five.pojo.entity.Product;
import com.five.pojo.entity.ProductImage;
import com.five.pojo.vo.MobileProductListVo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;


@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {

    @Resource
    private BrandService brandService;

    @Resource
    private ProductMapper productMapper;
    @Resource
    private ImageService imageService;
    @Resource
    private ProductImageService productImageService;


    /**
     * 扣减商品库存（带乐观锁，防止并发超卖）
     *
     * @param productId 商品ID
     * @param quantity  扣减数量
     * @return 影响行数（1=成功，0=失败）
     */
    @Override
    @Transactional
    public int reduceStock(Long productId, Integer quantity) {
        LambdaUpdateWrapper<Product> updateWrapper = new LambdaUpdateWrapper<Product>()
                .eq(Product::getId, productId)
                .ge(Product::getStockQuantity, quantity); // 库存充足校验

        Product product = getBaseMapper().selectOne(updateWrapper);

        product.setStockQuantity(product.getStockQuantity() - quantity);

        return baseMapper.update(product, updateWrapper);
    }

    @Override
    public int increaseStock(Long productId, Integer quantity) {
        LambdaUpdateWrapper<Product> updateWrapper = new LambdaUpdateWrapper<Product>()
                .eq(Product::getId, productId);
        Product product = getBaseMapper().selectOne(updateWrapper);
        product.setStockQuantity(product.getStockQuantity() + quantity);
        return baseMapper.update(product, updateWrapper);
    }

    @Override
    public Page<ProductAdminVo> findList(ProductQueryDto queryDto) {
        Page<Product> page = new Page<>(queryDto.getPage(), queryDto.getLimit());
        Page<ProductAdminVo> resultPage = productMapper.queryList(page, queryDto);
        return resultPage;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean save(ProductAddDto productAddDto) {
        // 先保存商品信息
        Product product = new Product();
        BeanUtils.copyProperties(productAddDto, product);
        int inserted = getBaseMapper().insert(product);
        //判断是否保存成功
        if (inserted > 0) {
            return addImages(product.getId(), productAddDto.getImages());
        }
        return false;
    }

    @Override
    public ProductDetailsVo getById(Long id) {
        ProductDetailsVo productDetailsVo = productMapper.queryById(id);
        List<String> images = productMapper.queryImagesByProductId(id);
        productDetailsVo.setImages(images);
        return productDetailsVo;
    }

    @Override
    public List<MobileProductListVo> queryProductByCategoryId(Long categoryId) {
        return productMapper.queryProductByCategoryId(categoryId);
    }

    @Override
    public boolean deleteProductById(Long id) {
        int delete = getBaseMapper().deleteById(id);
        if (delete > 0) {
            return deleteImages(id);
        }
        return false;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean updateProductById(ProductEditDto productEditDto) {
        Product product = new Product();
        BeanUtils.copyProperties(productEditDto, product);
        //修改商品信息
        getBaseMapper().updateById(product);
        //修改图片信息
        List<String> images = productEditDto.getImages();
//        删掉原先的图片
        boolean deleted = deleteImages(product.getId());
        if (deleted) {
            return addImages(product.getId(), images);
        }
        return false;
    }

    /**
     * 删除图片以及关系
     *
     * @param productId
     * @return
     */
    private boolean deleteImages(Long productId) {
        //删除对应的图片以及关系
        LambdaQueryWrapper<ProductImage> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProductImage::getProductId, productId);
        List<Long> imageIds = productImageService.list(queryWrapper).stream().map(ProductImage::getImageId).collect(Collectors.toList());
        //删除图片
        if (imageIds.isEmpty()){
            return true;
        }
        boolean batch = imageService.removeBatchByIds(imageIds);
        if (batch) {
            //删除关系
            return productImageService.remove(queryWrapper);
        }
        return false;
    }

    /**
     * 添加图片以及关系
     *
     * @param productId 商品ID
     * @param images    图片列表
     * @return
     */
    private boolean addImages(Long productId, List<String> images) {
        //手机图片的id信息
        List<Long> imageIds = images.stream().map(image -> {
            return Image.builder()
                    .imageUrl(image)
                    .build();
        }).collect(Collectors.toList()).stream().map(image -> {
            imageService.save(image);
            return image.getId();
        }).collect(Collectors.toList());
        //批量保存图片和商品关系
        boolean batch = productImageService.saveBatch(imageIds.stream().map(imageId -> {
            return ProductImage.builder()
                    .productId(productId)
                    .imageId(imageId)
                    .build();
        }).collect(Collectors.toList()));
        return batch;
    }

}